<template>
    <div class="roles-container">
      <el-breadcrumb separator-class="el-icon-arrow-right">
        <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
        <el-breadcrumb-item>权限管理</el-breadcrumb-item>
        <el-breadcrumb-item>角色列表</el-breadcrumb-item>
      </el-breadcrumb>
      <el-card>
        <!-- 添加按钮区域 -->
         <el-button type="primary" @click="addRoles">添加角色</el-button>
         <!-- 角色列表区域 -->
         <el-table
          :data="rolesList"
          stripe
          border
          style="width: 100%">
          <!-- 展开行 -->
          <el-table-column type="expand">
            <template slot-scope="scope">
              <!-- 使用v-for时一定要绑定key -->
              <!-- li是for循环的索引 -->
              <el-row v-for="(item, il) in scope.row.children" :key="item.id" :class="['roles-table-row', il===0 ? 'roles-table-row-one':'', 'vcenter']" >
                <!-- 渲染一级权限 -->
                <!-- 使所有的一级权限都处在每一行的第一列 -->
                <!-- el-col最好不要加类名 非则会出bug -->
                <el-col :span="5">
                  <div class="box-col">
                    <el-tag closable @close="removeRightsById(scope.row, item)">{{item.authName}}</el-tag>
                    <i class="el-icon-caret-right"></i>
                  </div>
                </el-col>
                <!-- 渲染二级和三级权限 -->
                <el-col :span="19">
                  <el-row v-for="(item_son,il) in item.children" :key="item_son.id" :class="[il === 0?'':'row-border', 'vcenter']">
                    <!-- 二级权限 -->
                    <el-col :span="5">
                      <div class="box-col">
                        <el-tag type="success" closable @close="removeRightsById(scope.row, item_son)">{{item_son.authName}}</el-tag>
                        <i class="el-icon-caret-right"></i>
                      </div>
                    </el-col>
                    <!-- 三级权限 -->
                    <el-col :span="19">
                        <el-tag v-for="item3 in item_son.children" :key="item3.id" class="box-col" type="warning" closable @close="removeRightsById(scope.row, item3)">
                          {{item3.authName}}
                        </el-tag>
                    </el-col>
                  </el-row>
                </el-col>
              </el-row>
            </template>
          </el-table-column>
          <el-table-column
            type="index"
            label="#">
          </el-table-column>
          <el-table-column
            prop="roleName"
            label="角色名称">
          </el-table-column>
          <el-table-column
            prop="roleDesc"
            label="角色描述"
            width="250px">
          </el-table-column>
          <el-table-column
            label="操作"
            width="350px">
            <template slot-scope="scope">
              <el-button type="primary" icon="el-icon-edit" size="mini" @click="editRoles(scope.row)">编辑</el-button>
              <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteRoles(scope.row.id)">删除</el-button>
              <el-button type="warning" icon="el-icon-setting" size="mini" @click="setRoles(scope.row)">分配权限</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-card>
      <!-- 添加角色对话框区域 -->
      <el-dialog title="添加角色" :visible.sync="rolesDialogVisible" width="400px" @close="resetRolesForm">
        <el-form :model="addRolesForm" :rules="rules"  label-width="100px" ref="rolesFormRef">
          <el-form-item label="角色名称" prop="roleName">
            <el-input v-model="addRolesForm.roleName" autocomplete="off"></el-input>
          </el-form-item>
          <el-form-item label="角色描述" prop="roleDesc">
            <el-input v-model="addRolesForm.roleDesc" autocomplete="off"></el-input>
          </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button @click="rolesDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="rolesFormValidate">确 定</el-button>
        </div>
      </el-dialog>
      <!-- 编辑角色对话框 -->
      <el-dialog
        title="编辑角色"
        :visible.sync="editDialogVisible"
        width="400px"
        @close="resetEditRolesForm">
        <el-form :model="editRolesForm" :rules="rules" ref="editRolesFormRef" label-width="80px">
          <el-form-item label="角色名称" prop="roleName">
            <el-input v-model="editRolesForm.roleName"></el-input>
          </el-form-item>
          <el-form-item label="角色描述" prop="roleDesc">
            <el-input v-model="editRolesForm.roleDesc"></el-input>
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="editDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="editRolesFormValidate">确 定</el-button>
        </span>
      </el-dialog>
      <!-- 分配权限对话框 -->
      <el-dialog
        title="分配权限"
        :visible.sync="setRolesDialogVisible"
        width="400px"
        @close="clearDefaultChecked">
        <!-- show-checkbox为每一个节点添加对话框 -->
        <!-- deagult-expand-all默认展开显示所有节点 -->
        <!-- 设置默认展开和默认选中的节点。需要注意的是，此时必须设置node-key，其值为节点数据中的一个字段名，该字段在整棵树中是唯一的。 -->
        <el-tree :data="rightsTree"
          :props="defaultProps"
          show-checkbox
          default-expand-all
          node-key="id"
          :default-checked-keys="defaultChecked"
          ref="treeRef">
          </el-tree>
        <span slot="footer" class="dialog-footer">
          <el-button @click="setRolesDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="allotRights">确 定</el-button>
        </span>
      </el-dialog>
    </div>
</template>

<script>
export default {
  name: 'Roles',
  created () {
    this.getRolesList()
  },
  data () {
    return {
      // 角色列表
      rolesList: [],
      // 添加角色对话框状态
      rolesDialogVisible: false,
      // 编辑角色对话框状态
      editDialogVisible: false,
      // 分配权限对话框状态
      setRolesDialogVisible: false,
      // 被修改角色的id
      editRolesId: '',
      // 要分配权限的角色的id
      roleId: '',
      // 分配权限对话框默认选中节点的id列表
      defaultChecked: [],
      // 添加角色表单内容
      addRolesForm: {
        roleName: '',
        roleDesc: ''
      },
      // 编辑角色表单内容
      editRolesForm: {
        roleName: '',
        roleDesc: ''
      },
      // 权限树
      rightsTree: [],
      // 树形控件属性绑定
      defaultProps: {
        // 父子组件通过children属性实现嵌套
        children: 'children',
        // 看到的是authName属性的值
        label: 'authName'
      },
      // 添加角色验证规则
      rules: {
        roleName: [
          { required: true, message: '请输入角色名称', trigger: 'blur' },
          { min: 2, max: 5, message: '长度在 2 到 5 个字符', trigger: 'blur' }
        ],
        roleDesc: [
          { min: 0, max: 10, message: '角色描述不要超过 10 个字符', trigger: 'blur' }
        ]
      }
    }
  },
  methods: {
    async getRolesList () {
      const { data: res } = await this.$http.get('roles')
      if (res.meta.status === 200) {
      //  获取成功
        this.rolesList = res.data
        return this.$message.success(res.meta.msg)
      }
      // 获取失败
      return this.$message.error('获取角色列表失败')
    },
    // 添加角色功能
    addRoles () {
      this.rolesDialogVisible = true
    },
    // 预验证角色表单
    rolesFormValidate () {
      this.$refs.rolesFormRef.validate(async (boolean) => {
        if (boolean) {
          // 表单验证通过
          const { data: res } = await this.$http.post('roles', this.addRolesForm)
          if (res.meta.status === 201) {
            // 添加角色成功
            this.rolesDialogVisible = false
            // 刷新用户列表
            this.getRolesList()
            return this.$message.success(res.meta.msg)
          }
          // 添加角色失败
          return this.$message.error('添加角色失败')
        }
        // 表单验证未通过
        this.$message.error('请输入正确的内容')
      })
    },
    // 重置用户表单功能
    resetRolesForm () {
      this.$refs.rolesFormRef.resetFields()
    },
    // 编辑角色功能
    editRoles (roles) {
      this.editDialogVisible = true
      // console.log(roles)
      // this.editRolesForm = roles
      this.editRolesForm.roleName = roles.roleName
      this.editRolesForm.roleDesc = roles.roleDesc
      this.editRolesId = roles.id
    },
    // 重置编辑用户表单功能
    resetEditRolesForm () {
      this.$refs.editRolesFormRef.resetFields()
    },
    // 预验证编辑角色表单
    editRolesFormValidate () {
      this.$refs.editRolesFormRef.validate(async (boolean) => {
        if (boolean) {
          // 表单验证通过
          // 关闭编辑角色表单
          this.editDialogVisible = false
          const { data: res } = await this.$http.put(`roles/${this.editRolesId}`, this.editRolesForm)
          if (res.meta.status === 200) {
            // 刷新角色列表
            this.getRolesList()
            return this.$message.success(res.meta.msg)
          }
          return this.$message.error('编辑角色失败')
        }
        // 表单验证为通过
        this.$message.error('请输入正确的内容')
      })
    },
    // 删除角色功能
    deleteRoles (id) {
      this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        // 点击确定按钮会执行函数then内的操作
        const { data: res } = await this.$http.delete('roles/' + id)
        if (res.meta.status === 200) {
          // 刷新角色列表
          this.getRolesList()
          return this.$message({
            type: 'success',
            message: '删除成功!'
          })
        }
        // 删除操作未成功
        this.$message({
          type: 'error',
          message: '删除失败!'
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    // 删除三级权限功能
    removeRightsById (role, right) {
      this.$confirm('此操作将取消该权限, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        const { data: res } = await this.$http.delete(`roles/${role.id}/rights/${right.id}`)
        if (res.meta.status === 200) {
          // 删除权限成功
          // 在这里刷新角色列表会重新渲染页面影响用户体验 最佳方案：给被修改的角色重新赋一次最新值
          // return this.getRolesList()
          role.children = res.data
          return this.$message.success(res.meta.msg)
        }
        // 删除角色失败
        this.$message.error('删除失败')
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    // 分配权限功能
    async setRoles (rights) {
      // 开启分配权限对话框
      this.setRolesDialogVisible = true
      // 挂载要分配权限的角色的id
      this.roleId = rights.id
      const { data: res } = await this.$http.get('rights/tree')
      if (res.meta.status === 200) {
        // console.log(res)
        this.rightsTree = res.data
        this.getThreeRightsId(rights, this.defaultChecked)
        return this.$message.success(res.meta.msg)
      }
      this.$message.error('获取权限列表失败')
    },
    // 获取三级权限的id
    getThreeRightsId (rights, Ids) {
      if (rights.children) {
        // 当前节点不包含三级权限
        rights.children.forEach(item => {
          this.getThreeRightsId(item, Ids)
        })
      } else {
        Ids.push(rights.id)
      }
    },
    // 清空分配权限对话框默认选中节点的id列表
    clearDefaultChecked () {
      this.defaultChecked = []
    },
    // 分配权限提交
    async allotRights () {
      // ... 将数组展开
      // getCheckedKeys方法将复选框状态为全选中的权限的id号打包成一个数组
      // getHalfCheckedKeys方法将复选框状态为半选中的权限的id号打包成一个数组
      const keys = [
        ...this.$refs.treeRef.getCheckedKeys(),
        ...this.$refs.treeRef.getHalfCheckedKeys()
      ]
      // 将数组设置为以逗号分隔
      const idStr = keys.join(',')
      // console.log(idStr)
      // { rids: idStr } 是请求体的格式
      const { data: res } = await this.$http.post(`roles/${this.roleId}/rights`, { rids: idStr })
      if (res.meta.status === 200) {
        this.setRolesDialogVisible = false
        this.getRolesList()
        return this.$message.success(res.meta.msg)
      }
      // 分配失败
      this.$message.error('分配权限失败')
    }
  }
}
</script>

<style lang="less" scoped>
.el-card {
  margin-top: 10px;
}
.el-table {
  margin-top: 10px;
}
.roles-table-row {
  margin-left: 47px;
  border-bottom: 1px solid #ccc;
}
.roles-table-col {
  margin: 10px 5px 10px 0;
}
.roles-table-row-one {
  border-top: 1px solid #ccc;
}
.box-col {
  margin: 5px 5px 5px 0;
}
.row-border {
  border-top: 1px solid #ccc;
}
// 此样式实现权限标签的垂直居中
.vcenter {
  display: flex;
  align-items: center;
}
</style>
